// __dll_template.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#include "__dll_template.h"

#include "ArgumentReflector.h"
#include "IndicatorInstance.h"

#include <algorithm>
#include <functional>
#include <stdexcept>

using namespace __dll_template;



C__dll_template::C__dll_template()
{
	return;
}

_DLL_EXP_(FXInt) __ReflectsIntValue( const FXInt ext_input)
{
	return ArgumentReflector::ReflectCopy<FXInt>(ext_input);
}

_FCN_STD_(FXDouble) __ReflectsDoubleValue(const FXDouble ext_input)
{
	return ArgumentReflector::ReflectCopy<FXDouble>(ext_input);
}

_FCN_STD_(FXChar*) __ReflectsCharValue(FXChar* ext_input)
{
	return ArgumentReflector::ReflectCopy<FXChar*>(ext_input);
}

_FCN_STD_(FXDouble) __ReflectArrayItemValue(const FXDouble* arr, const FXInt array_size, const FXInt nitem)
{

	if (FXERROR_VERIFY_IS_NULL(arr))
	{
		//TODO: rewrite function to proceed qNan as it done for scalar functions
		return(0.);
	}

	if ( array_size <= 0 )
	{
		return(0.);
	}

	if ( nitem < 0 || nitem >= array_size )
	{
		return(0.);
	}

	return (arr[nitem]);

};

_FCN_STD_(FXDouble) __GetNull()
{	
	return FXError::QuietNaN<FXDouble>();
};

_FCN_STD_(FXBool) __SortArray(FXDouble* arr, const FXInt size)
{	
	if (FXERROR_VERIFY_IS_NULL(arr))
	{
		return (false);
	}
	
	try
	{
		std::sort(arr, arr+size);
		return true;
	}
	catch (std::exception& )
	{	
		return false;
	}	
};

_FCN_STD_(FXInt) __SortStringArray(FXString* sarray, const int sarray_size)
{
	if(FXERROR_VERIFY_IS_NULL(sarray_size))
	{
		return -1;
	}
}


_FCN_STD_(FXInt) __Counter(const FXInt i)
{	
	count = count + i;
	return (count);
}

_FCN_STD_(FXDouble)	__GetRatesItemValue(const FXRateInfo* rates, const FXInt nrates, const FXInt shift, const  FXInt nrate)
{
	FXInt nitem = nrates - shift - 1;
	switch(nrate)
	{
	case RateItemTime:
		return double(rates[nitem]._ctm);
		break;
	case RateItemOpen:
		return rates[nitem]._open;
	case RateItemClose:
		return rates[nitem]._close;
	case RateItemHigh:
		return rates[nitem]._high;
	case RateItemLow:
		return rates[nitem]._low;
	case RateItemVolume:
		return rates[nitem]._vol;
	
		//TODO: return exception here
	default:
		return -1;
	}

	return 0;
}

_FCN_STD_(FXInt) __GetSharedVar()
{
	return sharedVar;
}

_FCN_STD_(void) __SetSharedVar(const FXInt new_val)
{
	sharedVar = new_val;
}


//<summary>
//	Returns the Id of new instance of indicator
//	The further work with indicator provides with that Id
//</summary>
_FCN_STD_(FXInt) __GetNewIndicatorInstance(FXRateInfo* rates, const FXInt symbol)
{
	return 0;
}

//<summary>
// Returns not 0 if need append new rate_info to the rates_info database of indicator (simply a vector yet);
//</summary>
_FCN_STD_(FXInt) __NeedAdditionalData(FXInt indicator_id, FXRateInfo last_comming_rate)
{
	return 0;
}

//<summary>
// Adds new  data to the indicators data (append new one) // no additional memory needed
//</summary>
_FCN_STD_(FXInt) __AddData(FXInt indicator_id, FXRateInfo new_rate)
{
	return 0;
}

//<summary>
// Return current indicator value at the dataset
//</summary>
_FCN_STD_(FXDouble) __GetIndicatorValue(FXInt indicator_id, FXInt shift_back)
{
	//TODO: write getter for IndicatorHandler
	//TODO: write destructor for IndicatorHandler
	//TODO: encourage with the mechanism of exception
	Indicator::IndicatorInstance* indicator_instance = indicator_handler.vec_handler.at(indicator_id - 1);
	return indicator_instance->Calc(shift_back);
}

//<summary>
// Removes Previously created indicator
//</summary>
_FCN_STD_(FXInt) __RemoveIndicator(FXInt indicator_id)
{
	indicator_handler.DeleteInstance(indicator_id);
	return 0;
}

//<summary>
//	Returns the Id of new SMA Indicator
//</summary>
_FCN_STD_(FXInt) __GetSMAInstance(const FXInt symbol, const FXInt timeframe, const FXRateInfo* rates, FXInt rates_size,  const FXInt period, const FXInt shift)
{
	Indicator::IndicatorInstance* sma_instance = new Indicator::SMAIndicatorInstance(symbol, timeframe, rates, rates_size, period, shift);
	return indicator_handler.AddInstance(sma_instance);
}

